package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.SystemClock;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.meta.business.client.api.ElevenDimensionsBusinessCardClient;
import com.meta.business.client.enums.BusinessCardEnum;
import com.meta.business.client.req.DirectCreateCardReq;
import com.meta.business.client.req.RegisterReq;
import com.sc.nft.dao.*;
import com.sc.nft.dto.UserFirstBuyDTO;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.SaasTaskBurialPointDTO;
import com.sc.nft.entity.vo.BusinessCardOrderAdminVO;
import com.sc.nft.entity.vo.CreateOrderVO;
import com.sc.nft.entity.vo.UserBusinessCardOrderPageVO;
import com.sc.nft.enums.MessageTopic;
import com.sc.nft.enums.OrderStatusEnum;
import com.sc.nft.enums.SaasTaskTypeEnum;
import com.sc.nft.enums.wallet.DaoWalletTypeEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.helper.MessageQueueHelper;
import com.sc.nft.service.BusinessCardOrderService;
import com.sc.nft.service.DaoWalletService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhangchao
 * @description 针对表【sc_business_card_order(订单sql表)】的数据库操作Service实现
 * @createDate 2024-07-08 18:30:28
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class BusinessCardOrderServiceImpl implements BusinessCardOrderService {
    private final BusinessCardOrderDao businessCardOrderDao;
    private final UserBusinessCardDao userBusinessCardDao;
    private final BusinessCardConfigDao businessCardConfigDao;
    private final UserCollectionDao userCollectionDao;
    private final BusinessCardHoldDao businessCardHoldDao;
    private final DaoWalletService daoWalletService;

    private final StaticDataDao staticDataDao;
    private final UserInfoDao userInfoDao;
    private final MessageQueueHelper messageQueueHelper;
    private final ElevenDimensionsBusinessCardClient elevenDimensionsBusinessCardClient;
    @Override
    public CreateOrderVO createOrder(UserInfo user) {
        CreateOrderVO createOrderVO = new CreateOrderVO();

        // 是否有已经支付成功的订单
        List<BusinessCardOrder> userIdByStatus = businessCardOrderDao.getUserIdByStatus(user.getId(), OrderStatusEnum.PAYMENT);
        if (CollUtil.isNotEmpty(userIdByStatus)) {
            throw new GlobalRunTimeException(ErrorCode.PAYMENT_ORDER);
        }

        // 验证当前是否有未支付的订单
        List<BusinessCardOrder> userHasAnyUnpaidOrders = businessCardOrderDao.getUserHasAnyUnpaidOrders(user.getId(), OrderStatusEnum.WAIT_PAY);
        if (CollUtil.isNotEmpty(userHasAnyUnpaidOrders)) {
            throw new GlobalRunTimeException(ErrorCode.WAIT_PAY_ORDER);
        }

        // 验证当前用户,是否已经购买过名片
        UserBusinessCard userBusinessCard = userBusinessCardDao.getByUserId(user.getId());
        // 已经购买过了的话就不让他在买了.
        if (BeanUtil.isNotEmpty(userBusinessCard)) {
            throw new GlobalRunTimeException(ErrorCode.OLD_BUSINESSCARD);
        }
        // 获取名片配置和价格.
        BusinessCardConfig businessCardConfig = businessCardConfigDao.getBusinessCardConfig();
        if (BeanUtil.isEmpty(businessCardConfig)) {
            throw new GlobalRunTimeException(ErrorCode.BUSINESSCARD_CONFIG_NOT_EXIST);
        }

        // 判定名片配置是否需要持有藏品,如果不需要的话,那么就直接创建订单,如果需要的话,那么就需要判定用户是否持有指定的藏品.
        if (businessCardConfig.getAppoint()) {
            // 判定用户是否持有指定的藏品.
            List<BusinessCardHold> holds = businessCardHoldDao.getConfigId(businessCardConfig.getId());
            if (BeanUtil.isEmpty(holds)) {
                throw new GlobalRunTimeException(ErrorCode.BUSINESSCARD_CONFIG_NOT_EXIST);
            }
            List<UserCollection> collectionIdByUserId = userCollectionDao.getCollectionIdByUserId(user.getId(), holds.stream().map(BusinessCardHold::getCollectionId).collect(Collectors.toList()));
            if (CollUtil.isEmpty(collectionIdByUserId)) {
                throw new GlobalRunTimeException(ErrorCode.USER_COLLECTION_NOT_EXIST);
            }
        }
        // 过期时间
        DateTime closeTime = DateUtil.offsetMinute(new Date(), 5);
        // 创建订单
        BusinessCardOrder businessCardOrder = new BusinessCardOrder();
        businessCardOrder.setUserId(user.getId());
        businessCardOrder.setBuyPayBalancePrice(BigDecimal.ZERO);
        businessCardOrder.setBuyPrice(businessCardConfig.getPrice());
        businessCardOrder.setStatus(OrderStatusEnum.WAIT_PAY);
        businessCardOrder.setImageUrl("https://cdn.gometa.com.cn/scnft/h5_default/47AD8B278EB5EA88");
        businessCardOrder.setFirstTitle("元宇宙名片");
        businessCardOrder.setOrderNo(OrderNoUtil.getOrderNo());
        businessCardOrder.setOrderTime(DateUtil.date());
        businessCardOrder.setCloseTime(closeTime);
        businessCardOrder.insert();

        createOrderVO.setOrderNo(businessCardOrder.getOrderNo());
        createOrderVO.setOrderId(businessCardOrder.getId());
        createOrderVO.setPurchaseNotes(staticDataDao.getByType("purchase_notes").getValue());
        createOrderVO.setOffsetTime(closeTime.getTime()- SystemClock.now());
        createOrderVO.setProductNum(businessCardConfig.getPrice().toPlainString());
        createOrderVO.setNowDate(DateUtil.now());
        createOrderVO.setExpirationTime(closeTime);
        return createOrderVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(BusinessCardOrder order) {
        if (ObjectUtil.isNull(order) || order.getStatus() != OrderStatusEnum.WAIT_PAY) {
            throw new GlobalRunTimeException("未找到支付订单");
        }
        DateTime now = DateTime.now();
        order.setPayTime(now);
        order.setStatus(OrderStatusEnum.PAYMENT);
        order.updateById();
        UserInfo userInfo = userInfoDao.getById(order.getUserId());
        if (!userInfo.getIsValid()) {
            userInfoDao.setIsValid(userInfo.getId());
            messageQueueHelper.sendMessage(MessageTopic.USER_FIRST_BUY, new UserFirstBuyDTO(userInfo.getId(), order.getId(), 3));
        }
        // 对用户进行第三方的名片注册-创建名片
        RegisterReq register = new RegisterReq();
        register.setOwner(userInfo.getUserUuid());
        register.setNickName(userInfo.getNickName());
        register.setMobile(userInfo.getUserTel());
        register.setLogo(userInfo.getAvatarImg());
        elevenDimensionsBusinessCardClient.register(register);

        DirectCreateCardReq directCreateCardReq = new DirectCreateCardReq();
        directCreateCardReq.setOwner(userInfo.getUserUuid());
        directCreateCardReq.setEnums(BusinessCardEnum.ADD_USER_BUSINESS_CARDS);
        elevenDimensionsBusinessCardClient.addUserBusinessCardNumber(directCreateCardReq);

            // 写入到用户持有名片表
            UserBusinessCard userBusinessCard=new UserBusinessCard();
            userBusinessCard.setUserId(userInfo.getId());
            userBusinessCard.setOrderNo(order.getOrderNo());
            userBusinessCard.setOrderId(order.getId());
            userBusinessCard.insert();

            // 发送任务.购买名片任务
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            @Override
            public void afterCommit() {
                SaasTaskBurialPointDTO saasTaskBurialPointDTO = new SaasTaskBurialPointDTO();
                messageQueueHelper.sendMessage(MessageTopic.DISK_TAKER, saasTaskBurialPointDTO.wallet(order.getUserId(), SaasTaskTypeEnum.BUSINESS_CARD_BUY, Convert.toBigDecimal(1), 0, order.getId()),SaasTaskTypeEnum.BUSINESS_CARD_BUY.name());
            }
        });
    }

    @Override
    public Page<UserBusinessCardOrderPageVO> userBusinessCardOrderPage(Page mp, Long userId) {
        return businessCardOrderDao.userBusinessCardOrderPage(mp,userId);
    }

    @Override
    public Page<BusinessCardOrderAdminVO> adminBusinessCardOrderPage(Page page,
                                                                     String orderNo,
                                                                     String userTel,
                                                                     String orderStartTime,
                                                                     String orderEndTime,
                                                                     String payStartTime,
                                                                     String payEndTime) {
        return businessCardOrderDao.adminBusinessCardOrderPage(page, orderNo, userTel, orderStartTime, orderEndTime, payStartTime, payEndTime);
    }

    @Override
    public Boolean orderSuccessStatus(Long id) {
        BusinessCardOrder businessCardOrder = businessCardOrderDao.getById(id);
        if (ObjectUtil.isNull(businessCardOrder)) {
            throw new GlobalRunTimeException("订单不存在");
        }
        return businessCardOrder.getStatus() == OrderStatusEnum.PAYMENT;
    }

    @Override
    public void closeOrder(Long id) {
        BusinessCardOrder order = businessCardOrderDao.getById(id);
        if (BeanUtil.isEmpty(order)) {
            throw new GlobalRunTimeException("订单不存在");
        }
        if (order.getStatus() == OrderStatusEnum.PAYMENT) {
            throw new GlobalRunTimeException("订单已支付,无法关闭");
        }
        if (!businessCardOrderDao.closeOrder(id)) {
            throw new GlobalRunTimeException("关闭订单失败");
        }
    }

    @Override
    public CreateOrderVO secondaryPayment(Long id) {
        BusinessCardOrder order = businessCardOrderDao.getById(id);
        if (BeanUtil.isEmpty(order)) {
            throw new GlobalRunTimeException("订单不存在");
        }
        if (order.getStatus() != OrderStatusEnum.WAIT_PAY) {
            throw new GlobalRunTimeException("订单已关闭或已支付");
        }
        CreateOrderVO createOrderVO = new CreateOrderVO();
        createOrderVO.setOrderId(order.getId());
        createOrderVO.setOffsetTime(order.getCloseTime().getTime() - SystemClock.now());
        createOrderVO.setProductNum(order.getBuyPrice().stripTrailingZeros().toPlainString());
        createOrderVO.setOrderNo(order.getOrderNo());
        createOrderVO.setNowDate(DateUtil.now());
        createOrderVO.setExpirationTime(order.getCloseTime());
        createOrderVO.setPurchaseNotes(staticDataDao.getByType("purchase_notes").getValue());
        return createOrderVO;
    }

    @Override
    public List<BusinessCardOrder> getCloseOrder() {
        return businessCardOrderDao.getCloseOrder();
    }

    @Override
    @SneakyThrows
    public void autoCloseOrder(BusinessCardOrder order) {
        Assert.isTrue(businessCardOrderDao.closeOrder(order.getId()), () -> new GlobalException("关闭订单失败"));
    }

    @Override
    public List<BusinessCardOrder> getWaitSettleOrder() {
        return businessCardOrderDao.getWaitSettleOrder();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void waitSettleOrder(BusinessCardOrder order) throws GlobalException {
        order.setSettleFlag(true);
        order.updateById();
        //221 写死结算给十一维
        daoWalletService.addBalance(221L,null,BigDecimal.valueOf(60L), BigDecimal.ZERO, DaoWalletTypeEnum.CARD_SETTLE,null);
    }

}




